package com.flute.framework.search.strategy;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.Query;

import com.flute.framework.search.LayerPayLoadFunction;
import com.flute.framework.search.LayerPayloadTermQuery;
import com.flute.framework.spliter.WordSpliter;
import com.flute.framework.stringprocessor.SplitStringProcessor;
import com.flute.tools.util.CombinationUtil;
import com.flute.tools.util.StringUtil;
import com.flute.tools.word.ISpliter;

public class MissWordSearchStrategy extends AbstractSearchStrategy {
	private int minus = 2;
	private int min = 2;
	private ISpliter spliter;

	public void setMinus(int minus) {
		this.minus = minus;
	}

	public void setMin(int min) {
		this.min = min;
	}

	@Override
	public Object getQuery(String string) {
		return getQuery(string, null);
	}

	private List<Object> getMinusAndMinStrings(String[] kws, int minus,
			int min, String sorter, float boost) {
		List<Object> queryList = new ArrayList<Object>();
		List<List> allList = new ArrayList<List>();
		for (int i = Math.max(min, kws.length - minus); i < kws.length; i++) {
			List<List> llist = CombinationUtil.getCombination(
					Arrays.asList(kws), i);
			for (List list : llist) {
				allList.add(list);
			}
		}

		for (List list : allList) {
			BooleanQuery lq = null;
			try {
				lq = new BooleanQuery();
			} catch (Exception e) {
			}
			for (Object obj : list) {
				LayerPayloadTermQuery query = new LayerPayloadTermQuery(
						new Term(fieldName, (String) obj),
						new LayerPayLoadFunction(), sorter);
				query.setBoost(boost);
				lq.add(query, BooleanClause.Occur.MUST);
			}
			queryList.add(lq);
		}

		return queryList;
	}

	@Override
	public Object getQuery(String string, String sorter) {
		return getQuery(string, sorter, 1f);
	}

	@Override
	public Object getQuery(String string, String sorter, float boost) {
		BooleanQuery bq = new BooleanQuery();
		string = standardize(string);

		if (spliter == null) {
			spliter = WordSpliter.getInstance();
		}
		String[] keys = new SplitStringProcessor(spliter).process(string)
				.split(StringUtil.UNIQUE_STRING);
		if (keys.length > 8) {
			for (String key : keys) {
				LayerPayloadTermQuery query = new LayerPayloadTermQuery(
						new Term(fieldName, key), new LayerPayLoadFunction(),
						sorter);
				query.setBoost(boost);
				bq.add(query, Occur.MUST);
			}
		} else {
			if (min <= 0) {
				min = 2;
			}
			if (minus <= 0) {
				minus = 2;
			}
			for (Object obj : getMinusAndMinStrings(keys, minus, min, sorter,
					boost)) {
				bq.add((Query) obj, Occur.SHOULD);
			}
		}

		return bq;
	}
}
